package com.qqt.csr.im.socketio;

import com.corundumstudio.socketio.SocketIOServer;
import com.qqt.csr.im.entity.Connection;
import com.qqt.csr.im.service.ConnectionService;
import com.qqt.csr.im.service.ServiceNodeService;
import com.qqt.csr.common.utils.IPUtil;
import com.qqt.csr.im.utils.DeviceCacheKeyUtil;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author: yang hao
 * @Date: 2024/10/15 14:33
 * @Description: socket-io 初始化
 **/
@Slf4j
@Component
@DependsOn(value = {"snowflakeUtil", "sensitiveWordBsFactory"})
public class SocketIOServerLaunch implements InitializingBean {

    @Value("${socketio.port}")
    private String port;
    @Autowired
    private ServiceNodeService serviceNodeService;
    @Autowired
    private ConnectionService connectionService;
    @Autowired
    private SocketIOServer socketServer;

    @Override
    public void afterPropertiesSet() throws Exception {
        socketServer.start();
        String ip = IPUtil.getIpAddress();
        serviceNodeService.online(ip, port);
        log.info("socket.io server started !{}:{}", ip, port);
    }

    @PreDestroy
    public void destroy() {
        stopSocketIO();
        disconnectAllClient();
        offlineServerNode();
    }

    private void disconnectAllClient() {
        try {
            List<Connection> connectionList = socketServer.getAllClients()
                    .stream()
                    .map(client -> (Connection) client.get("connection"))
                    .filter(Objects::nonNull)
                    .toList();
            connectionService.disconnect(connectionList);
            log.info("socket.io client disconnected !size:{}", connectionList.size());
        } catch (Exception e) {
            log.error("socket.io client disconnect failed !", e);
        }
    }

    private void offlineServerNode() {
        try {
            serviceNodeService.offline();
            log.info("service node offline !");
        } catch (Exception e) {
            log.error("service node offline failed !", e);
        }
    }

    private void stopSocketIO() {
        try {
            socketServer.stop();
        } catch (Exception e) {
            log.error("socket.io server stop failed !", e);
        }
    }
}
